console.log('\n------------\n');

// The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. 
console.log('Object.assign() 是ES6的方法');
console.log('Note that Object.assign() does not throw on null or undefined source values')
console.log('source可以是null/undefined, 会被忽略; target不可以, 会报错');
Object.assign({}, null, undefined)


console.log('Object.assign() 是浅克隆, 属性是对象的话, clone的是引用');
// Object.assign() copies the property reference when the property being assigned is an object.

console.log('merging objects, 注意修改的是target object, 返回的也是target object')
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.

console.log('多个对象具有相同的属性, 后面的对象属性值覆盖前面的')
var o1 = { a: 1, b: 1, c: 1 };
var o2 = { b: 2, c: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

console.log('原型链及不可枚举属性不会被复制')
var obj = Object.create({ foo: 1 }, { // foo is on obj's prototype chain.
  bar: {
    value: 2  // bar is a non-enumerable property.
  },
  baz: {
    value: 3,
    enumerable: true  // baz is an own enumerable property.
  }
});

var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }


console.log('Primitives will be wrapped, null and undefined will be ignored.');
console.log('不推荐copy原始类型');

var v1 = 'abc';
var v2 = true;
var v3 = 10;
var v4 = Symbol('foo');

var obj = Object.assign({}, v1, v2, v3, v4, null, undefined); 
// Note, only string wrappers can have own enumerable properties.
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

console.log('如果出现异常, copy将中断, 异常后面的属性值都为undefined');
var target = Object.defineProperty({}, 'foo', {
  value: 1,
	writable: false
}); // target.foo is a read-only property

//Object.assign(target,  { foo2: 3, foo: 3, foo3: 3 });
// TypeError: "foo" is read-only
// The Exception is thrown when assigning target.foo

// console.log(target.foo2); // 3, the first property of the source was copied successfully.
// console.log(target.foo);  // 1, exception is thrown here.
// console.log(target.foo3); // undefined, assign method has finished, foo3 will not be copied.

console.log('copy accessors: get/set method')
var obj = {
  foo: 1,
  get bar() {
    return 2;
  }
};

var copy = Object.assign({}, obj); 
// the value of copy.bar is obj.bar's getter's return value.
console.log( copy); 


